import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
import 'dart:convert';
import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:encrypt/encrypt.dart' as AES;
import 'package:crypto/crypto.dart';
import 'dart:convert';

// const String kHostUrl = 'http://192.168.20.110:8088/cardble';
const String kHostUrl = 'http://ble.wisdcloud.com/cardble';
 const String kLogUrl = 'http://gas.sqklrq.com/api/bluetooth/enclosure_log';
 const String kChangeStatusUrl = 'http://gas.sqklrq.com/api/bluetooth/enclosure';
// const String kLogUrl =
//    'http://tjdev.wisdcloud.com/api/bluetooth/enclosure_log';
// const String kChangeStatusUrl =
//    'http://tjdev.wisdcloud.com/api/bluetooth/enclosure';

const String kAesKey = '1234567891234567';
const String kAesIv = '1234567891234567';

const String kPlatformId = 'fgrq';

class ResultData {
  var data;
  bool success;
  int code;
  String desc;

  ResultData(this.data, this.success, this.code, this.desc);
}

///请求消息头设置
class HeaderInterceptors extends InterceptorsWrapper {
  @override
  onRequest(RequestOptions options) async {
    ///超时
    options.connectTimeout = 20000;
    options.receiveTimeout = 20000;
    options.responseType = ResponseType.json;
    options.contentType = 'application/json';
    return options;
  }
}

///请求前网络判断
class ErrorInterceptors extends InterceptorsWrapper {
  final Dio _dio;

  ErrorInterceptors(this._dio);

  @override
  onRequest(RequestOptions options) async {
    //没有网络
    var connectivityResult = await (new Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      DioError err = DioError()
        ..response = null
        ..type = DioErrorType.DEFAULT
        ..error = "网络异常,请检查联网情况";
      throw (err);
    }
    return options;
  }
}

///打印日志
class LogsInterceptors extends InterceptorsWrapper {
  @override
  onRequest(RequestOptions options) async {
    if (true) {
      print("请求url：${options.path}");
//      print('请求头: ' + options.headers.toString());
      if (options.data != null) {
        print('请求参数: ' + options.data.toString());
      }
    }
    return options;
  }

  @override
  onResponse(Response response) async {
    if (true) {
      if (response != null) {
        print('返回参数: ' + response.toString());
      }
    }
    return response; // continue
  }

  @override
  onError(DioError err) async {
    if (true) {
      print('请求异常: ' + err.toString());
      print('请求异常信息: ' + err.response?.toString() ?? "");
    }
    err.error = "服务器返回错误";
    return err;
  }
}

class HttpTool {
  Dio _dio = new Dio(); // 使用默认配置

  HttpTool() {
    _dio.interceptors.add(new HeaderInterceptors());

    _dio.interceptors.add(new LogsInterceptors());

    _dio.interceptors.add(new ErrorInterceptors(_dio));
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        return true;
      };
    };
  }

  ///发起网络请求
  ///[ url] 请求url
  ///[ params] 请求参数
  ///[ header] 外加头
  ///[ option] 配置
  netFetch(
    String url,
    params, {
    method = "post",
    String token,
    String aesKey,
  }) async {
    try {
      Response res = await _dio.request(url,
          data: params,
          options: Options(
              method: method,
              headers: token != null ? {'token': token} : null));
      Map response;
      if (res.data is Map) {
        response = res.data;
      } else {
        response = json.decode(res.data);
      }

      if (response["resultCode"].toString() == "0") {
        if (aesKey != null) {
          final key = AES.Key.fromUtf8(aesKey);
          final encrypter = AES.Encrypter(AES.AES(key, mode: AES.AESMode.ecb));
          final decrypted = encrypter.decrypt64(response['data']);
          return json.decode(decrypted);
        }
        return response['data'];
      } else {
        DioError err = DioError()
          ..response = res
          ..type = DioErrorType.DEFAULT
          ..error = response["resultMsg"].toString();
        return err;
      }
    } catch (e) {
      DioError err = DioError();
      if (e is! DioError) {
        print('$e');
        err.error = "解析失败";
      } else {
        DioError ers = e;
        err.error = ers.message;
        if (ers.type == DioErrorType.CONNECT_TIMEOUT ||
            ers.type == DioErrorType.RECEIVE_TIMEOUT) {
          err.error = "连接超时";
        }
      }
      return err;
    }
  }

  netFetch2(
    url,
    params, {
    method = "post",
    header,
    token,
  }) async {
    try {
      Response res = await _dio.request(url,
          data: params,
          options: Options(
            method: method,
            headers: {'access-token': token},
            contentType: 'application/json',
          ));
      Map response;
      if (res.data is Map) {
        response = res.data;
      } else {
        response = json.decode(res.data);
      }

      if (response["ResultCode"].toString() == "0" ||
          response["Code"].toString() == "0") {
        return response["Data"];
      } else {
        DioError err = DioError()
          ..response = res
          ..type = DioErrorType.DEFAULT
          ..error = response["Message"].toString();
        return err;
      }
    } catch (e) {
      DioError err = DioError();
      if (e is! DioError) {
        print('$e');
        err.error = "解析失败";
      } else {
        DioError ers = e;
        err.error = ers.message;
        if (ers.type == DioErrorType.CONNECT_TIMEOUT ||
            ers.type == DioErrorType.RECEIVE_TIMEOUT) {
          err.error = "连接超时";
        } else {
          err.error = '网络链接错误';
        }
      }
      return err;
    }
  }

  static void post(String url, Map<String, dynamic> pamars,
      Function(Map response) succss, Function(dynamic error) faild) async {
    try {
      var res = await httpTool.netFetch(url, pamars);
      succss(res);
    } catch (e) {
      if (e is DioError) {
        faild(e);
      } else {
        print("请求失败:解析失败！");
        DioError err = DioError()
          ..response = null
          ..type = DioErrorType.DEFAULT
          ..error = "服务器返回错误";
        faild(err);
      }
    }
  }
}

final HttpTool httpTool = new HttpTool();

class NetWorkManager {
  static login(String sn) async {
    Map pamars = Map();
    pamars['cmd'] = 'login';
    pamars['pltformId'] = kPlatformId;
    pamars['readerNo'] = sn;

    var res = await httpTool.netFetch(kHostUrl, pamars);
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static getReadCommand(
    String sn,
    String token,
    String aesKey, {
    String ctrlCode = 'XA',
    String password,
  }) async {
    Map pamars = Map();
    pamars['cmd'] = 'getReadCommand';
    pamars['ctrlCode'] = ctrlCode;
    if (password != null) pamars['datas'] = password;

    var res = await httpTool.netFetch(
      kHostUrl,
      pamars,
      token: token,
      aesKey: aesKey,
    );
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static getPasswordCommand(String sn, String token, String aesKey,
      {String ctrlCode = 'QC'}) async {
    Map pamars = Map();
    pamars['cmd'] = 'getPwdCommand';
    pamars['ctrlCode'] = ctrlCode;

    var res = await httpTool.netFetch(
      kHostUrl,
      pamars,
      token: token,
      aesKey: aesKey,
    );
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static readCard(String data, String token, String aesKey,
      {String ctrlCode = 'XA'}) async {
    Map pamars = Map();
    pamars['cmd'] = 'readCard';
    pamars['ctrlCode'] = ctrlCode;
    pamars['datas'] = data;
    var res =
        await httpTool.netFetch(kHostUrl, pamars, token: token, aesKey: aesKey);
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static writeCard(
    String aesKey,
    String token, {
    String ctrlCode = 'XA',
    String cardNo,
    String cardGas,
    String cardMemo = '{}',
    String cardNumber,
    String cardData,
    String meterID,
  }) async {
    Map pamars = Map();
    pamars['cmd'] = 'getWriteCommand';
    pamars['ctrlCode'] = ctrlCode;
    pamars['cardNo'] = cardNo;
    pamars['cardGas'] = cardGas;
    pamars['cardMemo'] = cardMemo;
    pamars['datas'] = cardData;
    if (cardNumber != null && cardNumber.isNotEmpty)
      pamars['cardNumber'] = cardNumber;
    if (meterID != null && meterID.isNotEmpty) pamars['meterId'] = meterID;
    var res =
        await httpTool.netFetch(kHostUrl, pamars, token: token, aesKey: aesKey);
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static saveLog(
    String token, {
    String orderID,
    String userNo,
    String sn,
    String content,
    bool status,
    String ctrlCode,
  }) async {
    Map pamars = Map();
    pamars['LogOrderId'] = orderID;
    pamars['LogUserNo'] = userNo;
    pamars['LogBluetoothNo'] = sn;
    pamars['LogEnclosureStatus'] = status;
    pamars['LogContent'] = content;
    pamars['LogCtrlCode'] = ctrlCode;

    var res = await httpTool.netFetch2(kLogUrl, pamars, token: token);
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }

  static changeOrderStatus(String cipherText, String token) async {
    Map pamars = Map();
    final key = AES.Key.fromUtf8(kAesKey);
    final iv = AES.IV.fromUtf8(kAesIv);
    final encrypter = AES.Encrypter(AES.AES(
      key,
      mode: AES.AESMode.cbc,
    ));
    final encrypted = encrypter.encrypt(cipherText, iv: iv);
    print('加密前：' + cipherText);
    print('加密后：' + encrypted.base64);

    pamars['CipherText'] = encrypted.base64;
    var res = await httpTool.netFetch2(kChangeStatusUrl, pamars, token: token);
    if (res is DioError) {
      DioError err = res;
      return ResultData(null, false, -1, err.error);
    } else {
      return ResultData(res, true, 0, "登录成功！");
    }
  }
}
